package signature

import (
	"crypto/rsa"
	"sync"
)

// Key 签名秘钥，可能只有公钥，也可能包含私钥
type Key struct {
	sync.RWMutex
	name string
	priv *rsa.PrivateKey
	pub  *rsa.PublicKey
}

// Name 秘钥的名字
func (key *Key) Name() string { return key.name }

func (key *Key) cachePriv() *rsa.PrivateKey {
	key.RLock()
	defer key.RUnlock()
	return key.priv
}

func (key *Key) cachePub() *rsa.PublicKey {
	key.RLock()
	defer key.RUnlock()
	return key.pub
}

// Priv 获取私钥
func (key *Key) Priv() (*rsa.PrivateKey, error) {
	if priv := key.cachePriv(); priv != nil {
		return priv, nil
	}
	priv, err := ReadPrivKey(key.Name())
	if err != nil {
		return nil, err
	}
	key.Lock()
	defer key.Unlock()
	key.priv = priv
	key.pub = &priv.PublicKey
	return key.priv, nil
}

// Pub 获取公钥
func (key *Key) Pub() (*rsa.PublicKey, error) {
	if pub := key.cachePub(); pub != nil {
		return pub, nil
	}
	_, err := key.Priv()
	if err == nil {
		return key.cachePub(), nil
	}
	pub, err := ReadPubKey(key.Name())
	if err != nil {
		return nil, err
	}
	key.Lock()
	defer key.Unlock()
	key.pub = pub
	return key.pub, nil
}

var keyStore = &struct {
	sync.Mutex
	store map[string]*Key
}{
	store: make(map[string]*Key),
}

// GetKey 获取一个指定名字的Key
func GetKey(keyName string) *Key {
	keyStore.Lock()
	defer keyStore.Unlock()
	if key, ok := keyStore.store[keyName]; ok {
		return key
	}
	key := &Key{name: keyName}
	keyStore.store[keyName] = key
	return key
}
